#include "Common.h"

const size_t Tool::group_num[5] = { 0, 15, 71, 127, 183 };

// 取前4/8字节存下一内存块地址
void*& Tool::NextObj(void* obj) // static函数使用不用对类进行实例化
{
    // void*无法直接解引用，强转成void**二级指针，在解引用为一个指针的大小
    return *(void**)obj;
}

// 对齐内存
size_t Tool::RoundUp(size_t size)
{
    if (size <= 128) return _RoundUp(size, 8); // 2.修改return
    else if (size <= 1024) return _RoundUp(size, 16);
    else if (size <= 8 * 1024) return _RoundUp(size, 128);
    else if (size <= 64 * 1024) return _RoundUp(size, 1024);
    else if (size <= 256 * 1024) return _RoundUp(size, 8 * 1024);
    else return _RoundUp(size, 2 << page_shift); // 超过256KB
}

//  在哈希表中位置
size_t Tool::Index(size_t size) // size 为对齐后内存
{
    if (size <= 128) return size / 8;
    else if (size <= 1024) return (size - 128) / 16 + group_num[1];
    else if (size <= 8 * 1024) return (size - 1024) / 128 + group_num[2];
    else if (size <= 64 * 1024) return (size - 8 * 1024) / 1024 + group_num[3];
    else if (size <= 256 * 1024) return (size - 64 * 1024) / 8 * 1024 + group_num[4];
    else assert(false);
    return -1;
}

// size大小内存块能申请的最大数量
size_t Tool::NumMoveSize(size_t size)
{
    assert(size > 0);
    int num = max_byte / size;
    if (num > 512) return 512;
    else if (num < 2) return 2;
    return num;
}

// size大小内存块最大申请页数
size_t Tool::NumMovePage(size_t size)
{
    assert(size > 0);
    size_t nPage = (NumMoveSize(size) * size) >> page_shift;
    return nPage > 1 ? nPage : 1;
}

size_t Tool::_RoundUp(size_t size, size_t alignNum)
{
    return size % alignNum == 0 ? size : (size / alignNum + 1) * alignNum;
}


FreeList::FreeList() :_freeList(nullptr), _size(0), _maxSize(1) {}
size_t FreeList::GetSize() { return _size; }
size_t& FreeList::GetMaxSize() { return _maxSize; } // 引用，直接用这个接口修改maxSize
bool FreeList::Empty() { return _freeList == nullptr; }

void FreeList::Push(void* obj)
{
    assert(obj);
    Tool::NextObj(obj) = _freeList;
    _freeList = obj;
    _size++;
}
void* FreeList::Pop()
{
    void* obj = _freeList;
    _freeList = Tool::NextObj(_freeList);
    _size--;
    return obj;
}
void FreeList::PushRange(void* start, void* end, size_t n)
{
    assert(start && end);
    Tool::NextObj(end) = _freeList;
    _freeList = start;
    _size += n;
}
void FreeList::PopRange(void*& start, void*& end, size_t size) // 输出型形参
{
    assert(size > 0);
    start = end = _freeList;
    for (int i = 0; i < size - 1; i++)
        end = Tool::NextObj(end);
    _freeList = Tool::NextObj(end);
    Tool::NextObj(end) = nullptr;
    _size -= size;
}



SpanList::SpanList()
{
    _head = new Span;
    _head->_next = _head;
    _head->_prev = _head;
}

bool SpanList::Empty() { return _head->_next == _head; }
Span* SpanList::Begin() { return _head->_next; }
Span* SpanList::End() { return _head; }

void SpanList::Insert(Span* pos, Span* span)
{
    assert(pos && span);
    Span* prev = pos->_prev;
    prev->_next = span;
    span->_prev = prev;
    span->_next = pos;
    pos->_prev = span;
}
void SpanList::Erase(Span* pos)
{
    assert(pos && pos != _head);
    Span* prev = pos->_prev;
    prev->_next = pos->_next;
    pos->_next->_prev = prev;
}
void SpanList::PushFront(Span* span)
{
    assert(span);
    Insert(Begin(), span);
}
Span* SpanList::PopFront()
{
    Span* span = Begin();   
    Erase(span);
    return span;
}
std::mutex& SpanList::GetMtx()
{
    return _mtx;
}




